/******************************************************************************
 * Copyright (C) 2017 Chengdu Dlhd information industry co. LTD.
 * All Rights Reserved.
 * 本软件为成都顶联互动信息产业有限公司开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、复制、修改或发布本软件.
 *****************************************************************************/
package net.dgg.dggcloud.service.jrcrm.service.cms;

import net.dgg.dggcloud.core.cache.CacheManager;
import net.dgg.dggcloud.core.constants.Constants;
import net.dgg.dggcloud.core.util.ConfigLoader;
import net.dgg.dggcloud.core.util.DateUtil;
import net.dgg.dggcloud.core.util.StringUtils;
import net.dgg.dggcloud.service.common.base.service.BaseService;
import net.dgg.dggcloud.service.common.exception.BizException;
import net.dgg.dggcloud.service.common.util.HttpUtility;
import net.dgg.dggcloud.service.entity.user.User;
import net.dgg.dggcloud.service.iboss.utils.Property;
import net.dgg.dggcloud.service.jrcrm.constant.CommonConstant;
import net.dgg.dggcloud.service.jrcrm.dao.cms.BillNumberRuleDao;
import net.dgg.dggcloud.service.jrcrm.entity.cms.BillNumberRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @ClassName 〈BillNumberService>
 * @Description 单据号service
 * @Author 朱永波
 * @Date 2017/11/3 14:55
 */
@Service
public class BillNumberRuleService extends BaseService {
    @Autowired
    private BillNumberRuleDao billNumberRuleDao;

    /**
     * 根据ID查询单据号
     *
     * @param id
     * @return
     */
    public BillNumberRule getById(Long id) {
        return super.repository.get(BillNumberRule.class, id);
    }

    /**
     * 保存单据号
     *
     * @param billNumberRule
     * @param loger
     * @return
     */
    public void saveBillNumberRule(BillNumberRule billNumberRule, User loger) {
        try {

            if (null != billNumberRule.getId()) {
                BillNumberRule billNumberRuleUp = this.repository.get(BillNumberRule.class, billNumberRule.getId());
                billNumberRuleUp.setCode(billNumberRule.getCode());
                billNumberRuleUp.setName(billNumberRule.getName());
                billNumberRuleUp.setBillTag(billNumberRule.getBillTag());
                billNumberRuleUp.setUpdaterUser(loger);
                billNumberRuleUp.setIsYear(billNumberRule.getIsYear());
                billNumberRuleUp.setIsMonth(billNumberRule.getIsMonth());
                billNumberRuleUp.setIsDay(billNumberRule.getIsDay());
                billNumberRuleUp.setIsZero(billNumberRule.getIsZero());
                billNumberRuleUp.setText(billNumberRule.getText());
                billNumberRuleUp.setSerialNumLen(billNumberRule.getSerialNumLen());
//                Map smap = new HashMap();
//                smap.put("code", treeBook.getCode());
//                smap.put("id", treeBook.getId());
//                if (treeBookDao.queryTreeBookRepeat(smap) > 0) {
//                    throw new BizException("字典编码已存在", 10001);
//                }
                this.repository.saveOrUpdate(billNumberRuleUp);
            } else {
                Map smap = new HashMap();
//                smap.put("code", treeBook.getCode());
//                if (treeBookDao.queryTreeBookRepeat(smap) > 0) {
//                    throw new BizException("单据号编码已存在", 10001);
//                }
                long id = this.keyWorker.nextId();
                billNumberRule.setId(id);
                billNumberRule.setLastZeroDay(new Date());
                billNumberRule.setSerialNum(0);
                billNumberRule.setCreateUser(loger);
                this.repository.save(billNumberRule);
            }
        } catch (Exception e) {
            logger.error("新增字典失败！" + e.getLocalizedMessage());
            throw new BizException("新增字典失败！" + e.getLocalizedMessage(), 10001);
        }
    }

    /**
     * 查询单据号分页列表
     *
     * @param map
     * @return
     */
    public List<Map> queryBillNumberRuleByMap(Map map) {
        return billNumberRuleDao.queryBillNumberRuleByMap(map);
    }

    /**
     * 分页查询总数
     *
     * @param map
     * @return
     */
    public Integer countBillNumberRuleByMap(Map map) {
        return billNumberRuleDao.countBillNumberRuleByMap(map);
    }

    /**
     * 按单据号编码获取单据号
     *
     * @param code 单据分类编码(必传)
     * @return
     */
    public String updateBillNumberByCode(String code) {
        try {
            Map map = new HashMap();
            map.put("code",code);
            String billNumber = HttpUtility.getRest(new ConfigLoader().getVaule("bill_number_url"),map);
            if(StringUtils.isBlank(billNumber))
                throw new BizException("获取单据号失败，请重试！",10001);
            return billNumber;
        } catch (IOException e) {
            logger.error("获取单据号失败！" + e.getLocalizedMessage());
            throw new BizException("获取单据号失败",10001);
        }
    }

    /**
     * 按单据号编码获取单据号
     *
     * @param code 单据分类编码(必传)
     * @return
     */
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public String getBillNumber(String code) {
            if (StringUtils.isBlank(code)) {
                throw new BizException("单据分类编码不能为空", 10001);
            }
            Map condi = new HashMap();
            condi.put("code", code);
            BillNumberRule rule = billNumberRuleDao.find4Code(condi);
            if (null == rule) {
                throw new BizException("单据规则不存在", 10001);
            }
            Object serialNumObj = CacheManager.getOperator().get(Constants.BILL_NUMBER_INC + code);
            Integer serialNum = 0;
            if (null == serialNumObj) {
                serialNum = rule.getSerialNum() + 500;
                CacheManager.getOperator().put(Constants.BILL_NUMBER_INC + code, serialNum);
                rule.setSerialNum(serialNum);
                billNumberRuleDao.updateByHiber(rule);
            } else {
                Long serialNumInc = CacheManager.getOperator().incr(Constants.BILL_NUMBER_INC + code);
                if (null != serialNumInc) {
                    serialNum = serialNumInc.intValue();
                    int i = serialNum % 500;
                    if (0 == i) {
                        rule.setSerialNum(serialNum);
                        billNumberRuleDao.updateByHiber(rule);
                    }
                }
            }


            //单据日期格式
            int isYear = rule.getIsYear();
            int isMonth = rule.getIsMonth();
            int isDay = rule.getIsDay();
//            String today = DateUtil.fromDateP("yyyyMMdd");
            if (!CacheManager.getOperator().exists(Constants.BILL_NUMBER_THIS_DATE)) {
                CacheManager.getOperator().put(Constants.BILL_NUMBER_THIS_DATE,DateUtil.fromDateP("yyyyMMdd"));
            }
            String today = CacheManager.getOperator().get(Constants.BILL_NUMBER_THIS_DATE,String.class);
            String year = (1 == isYear ? today.substring(0, 4) : "");
            String month = (1 == isMonth ? today.substring(4, 6) : "");
            String day = (1 == isDay ? today.substring(6, 8) : "");
            //手动标志
            String tag = StringUtils.isBlank(rule.getBillTag()) ? "" : rule.getBillTag().trim();
            //补足位数
            String serialNumIncs = getFullNumber(serialNum, rule.getSerialNumLen());
            StringBuilder billNumber = new StringBuilder();
            //格式：tag+date+serialNum
            billNumber.append(tag).append(year).append(month).append(day).append(serialNumIncs);
            return billNumber.toString();
    }

    /**
     * 单据号长度补0
     *
     * @param nextNumber
     * @param len
     * @return
     */
    private String getFullNumber(int nextNumber, int len) {
        String n = String.valueOf(nextNumber);
        if (n.length() >= len) return n;
        StringBuffer number = new StringBuffer();
        for (int i = 0; i < (len - n.length()); i++) {
            number.append("0");
        }
        number.append(n);
        return number.toString();
    }
}
